package internal

import (
	"New-lesson-part2/proto/pb"
	"encoding/json"
	"fmt"
	"github.com/hashicorp/consul/api"
	"github.com/nacos-group/nacos-sdk-go/v2/clients"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"github.com/nacos-group/nacos-sdk-go/v2/vo"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"strconv"
)

var fileName = "./dev-config.yaml"
var NacosConf NacosConfig
var AppConf AppConfig

func init() {
	//初始化从nacos中拿配置信息
	initNacosFrom()
	//初始化DB操作
	InitDB()
	//初始化redis操作
	InitRedis() //初始化redis连接操作
	initLog()   //初始化log操作
	//初始化productClient客户端
	InitProductClient()
	//初始化购物车客户端信息
	ShopCartInit()
	//初始化StockClient
	InitStockClient()

}

func initNacosFrom() {
	serverConfigs := []constant.ServerConfig{ //指定nacos服务地址.配置连接信息
		{
			IpAddr: "192.168.75.6", //这里是指定nacos的服务连接地址
			Port:   8848,           //指定端口号
		},
	}
	clientConfig := constant.ClientConfig{ //配置客户端配置信息.用来做客户端初始化配置.
		TimeoutMs:            5000,                                   //连接超时时间
		NamespaceId:          "8774e75a-fbe8-4b29-8194-4e70f482924d", //这里写的是命名空间的地址.用哪个就写哪个,这里用的是dev的命名空间
		CacheDir:             "nacos/cache",                          //nacos缓存目录
		NotLoadCacheAtStart:  true,                                   //配置是否在服务启动时直接加载缓存??
		UpdateCacheWhenEmpty: false,                                  //配置当缓存为空的时候进行主动更新
		LogDir:               "nacos/log",                            //日志目录
		LogLevel:             "debug",                                //日志级别
	}
	configClient, err := clients.CreateConfigClient(map[string]interface{}{ //根据nacos的地址信息和需要的配置页面信息生成一个客户端.
		"serverConfigs": serverConfigs,
		"clientConfig":  clientConfig,
	})
	if err != nil {
		panic(err)
	}
	content, err := configClient.GetConfig(vo.ConfigParam{ //读取在页面上配置好de相关信息.
		// 这里用的是dev分组中的account_web配置.以后这里的配置可以使用viper进行参数配置.
		DataId: "product.json",
		Group:  "dev",
	})
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal([]byte(content), &AppConf)
	if err != nil {
		fmt.Println(err)
		zap.S().Error("main函数反序列化错误")
	}

}

var ProductClient pb.ProductServiceClient
var ShopCartClient pb.ShopCartServiceClient
var OrderClient pb.OrderServiceClient
var StockClient pb.StockServiceClient

func InitProductClient() {
	consulConfig := api.DefaultConfig()
	addr := fmt.Sprintf("%s:%d", AppConf.ConsulConfig.Host, AppConf.ConsulConfig.Port)
	consulConfig.Address = addr
	consulClient, err := api.NewClient(consulConfig)
	if err != nil {
		zap.S().Error("consul客户端创建失败", err.Error())
	}
	service, _, err := consulClient.Health().Service("product_srv", "", true, nil)
	if err != nil {
		zap.S().Error("获取consul中注册相关服务失败.", err.Error())
	}
	target := service[0].Service.Address + ":" + strconv.Itoa(service[0].Service.Port)
	address := target
	conn, err := grpc.Dial(address,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`)) //添加负载均衡
	if err != nil {
		zap.S().Error("Grpc Dialing Is failed ")
	}
	ProductClient = pb.NewProductServiceClient(conn)
}

func InitStockClient() {
	consulConfig := api.DefaultConfig()
	addr := fmt.Sprintf("%s:%d", AppConf.ConsulConfig.Host, AppConf.ConsulConfig.Port)
	consulConfig.Address = addr
	consulClient, err := api.NewClient(consulConfig)
	if err != nil {
		zap.S().Error("consul客户端创建失败", err.Error())
	}
	service, _, err := consulClient.Health().Service("stock_srv", "", true, nil)
	if err != nil {
		zap.S().Error("获取consul中注册相关服务失败.", err.Error())
	}
	target := service[0].Service.Address + ":" + strconv.Itoa(service[0].Service.Port)
	address := target
	conn, err := grpc.Dial(address,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`)) //添加负载均衡
	if err != nil {
		zap.S().Error("Grpc Dialing Is failed ")
	}
	StockClient = pb.NewStockServiceClient(conn)
}

func InitOrderClient() {
	consulConfig := api.DefaultConfig()
	addr := fmt.Sprintf("%s:%d", AppConf.ConsulConfig.Host, AppConf.ConsulConfig.Port)
	consulConfig.Address = addr
	consulClient, err := api.NewClient(consulConfig)
	if err != nil {
		zap.S().Error("consul客户端创建失败", err.Error())
	}
	service, _, err := consulClient.Health().Service("", "", true, nil)
	if err != nil {
		zap.S().Error("获取consul中注册相关服务失败.", err.Error())
	}
	target := service[0].Service.Address + ":" + strconv.Itoa(service[0].Service.Port)
	address := target
	conn, err := grpc.Dial(address,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`)) //添加负载均衡
	if err != nil {
		zap.S().Error("Grpc Dialing Is failed ")
	}
	OrderClient = pb.NewOrderServiceClient(conn)
}

func ShopCartInit() {
	consulConfig := api.DefaultConfig()
	addr := fmt.Sprintf("%s:%d", AppConf.ConsulConfig.Host, AppConf.ConsulConfig.Port)
	consulConfig.Address = addr
	consulClient, err := api.NewClient(consulConfig)
	if err != nil {
		zap.S().Error("consul客户端创建失败", err.Error())
	}
	service, _, err := consulClient.Health().Service("cart_order_srv", "", true, nil)
	if err != nil {
		zap.S().Error("获取consul中注册相关服务失败.", err.Error())
	}
	target := service[0].Service.Address + ":" + strconv.Itoa(service[0].Service.Port)
	address := target
	conn, err := grpc.Dial(address,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`)) //添加负载均衡
	if err != nil {
		zap.S().Error("Grpc Dialing Is failed ")
	}
	ShopCartClient = pb.NewShopCartServiceClient(conn)
}
